/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package pl.cezary.butler.walili.server.db.tasks;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.sql.DataSource;
import org.springframework.jdbc.datasource.SingleConnectionDataSource;
import pl.cezary.butler.walili.server.db.Database;
import pl.cezary.butler.walili.server.db.IdFactory;
import pl.cezary.butler.walili.server.db.utils.JdbcTemplate;

/**
 *
 * @author Przemysław Bałdyga
 */
public abstract class DbTask implements Runnable {

    private static final Logger log = Logger.getLogger(DbTask.class.getName());
    //private Database bd;
    private boolean runned = false;
    private Connection con;
    private boolean fail;
    private JdbcTemplate jdbcTemplate;
    private SingleConnectionDataSource ds;
    private IdFactory idFactory;

    protected DataSource getDS() {            
        return ds;
    }
    
    void setTaskConnection(Connection con){       
        assert(con!=null);
        this.con = con;
        ds = new SingleConnectionDataSource(con, true);
    }
    
    void setIdFactory(IdFactory idFactory){
        this.idFactory = idFactory;
    }
    
    public void setExecutionContext(Connection con, IdFactory idFactory){
        assert(idFactory!=null);
        setTaskConnection(con);
        setIdFactory(idFactory);
    }
    
    protected IdFactory getIdFactory(){
        return idFactory;
    }

    /*public Database getIdFactory() {
        return bd;
    }*/

    /*public Connection getConnection() {
        return con;
    }*/

    public abstract void execute() throws SQLException;

    @Override
    public final void run() {
        try {
            if (runned) {
                final String komunikat = "ZadanieBazaDanych nie zezwala na wielokrotne uzywanie tego samego zadania, nie uruchamiam!!!";
                log.warning(komunikat);
                throw new IllegalStateException(komunikat);
            }
            runned = true;
            execute();
        } catch (Exception ex) {
            fail("Błąd SQL podczas wykonywania zadania", ex);
            
        } finally {
            try {
                try {
                    if (!con.getAutoCommit() && con.getTransactionIsolation() != Connection.TRANSACTION_NONE) {
                        con.commit();
                    }
                } catch (SQLException ex) {
                    fail("Blad podczas zatwierdzania transakcji", ex);
                }
                if (con != null) {
                    con.close();
                }
            } catch (SQLException ex) {
                fail("Błąd SQL podczas zamykania zadania", ex);
            }
        }
    }

    private void fail(final String blad, Exception ex) {
        fail = true;        
        log.log(Level.SEVERE, blad, ex);
        throw new RuntimeException("Błąd zapytania");
    }
    

    protected JdbcTemplate getJdbcTemplate() {
        if (jdbcTemplate == null) {
            jdbcTemplate = new JdbcTemplate(getDS());
        }
        return jdbcTemplate;
    }

    public boolean isFail() {
        return fail;
    }
}
